


// Event.h

#pragma once
#include <list>
#include <algorithm>
#include "EmptyType.h"
#include "Functor.h"


namespace Loki
{





	template <typename _R>
	struct handler_type_base
	{
		typedef _R result_type;
		typedef EmptyType param1_type;
		typedef EmptyType param2_type;
		typedef EmptyType param3_type;
		typedef EmptyType param4_type;
		typedef EmptyType param5_type;
		typedef EmptyType param6_type;
	};

	//
	// handler_base
	//
	template <typename _R, typename _ParamList>
	struct handler_base;

	// 0 param
	template <typename _R>
	struct handler_base<_R, void> : public handler_type_base<_R>
	{
		virtual _R operator() ( void ) = 0;
		virtual bool is_equal(handler_base*) = 0;
		virtual handler_base* clone() = 0;
	};

	// 1 param
	template <typename _R, typename _P1>
	struct handler_base<_R, TYPE_LIST1( _P1 ) > : public handler_type_base<_R>
	{
		typedef _P1 param1_type;

		virtual _R operator() ( _P1 ) = 0;
		virtual bool is_equal(handler_base*) = 0;
		virtual handler_base* clone() = 0;
	};

	// 2 param
	template <typename _R, typename _P1, typename _P2>
	struct handler_base<_R, TYPE_LIST2( _P1, _P2 ) > : public handler_type_base<_R>
	{
		typedef _P1 param1_type;
		typedef _P2 param2_type;

		virtual _R operator() ( _P1, _P2 ) = 0;
		virtual bool is_equal(handler_base*) = 0;
		virtual handler_base* clone() = 0;
	};

	// 3 param
	template <typename _R, typename _P1, typename _P2, typename _P3>
	struct handler_base<_R, TYPE_LIST3( _P1, _P2, _P3 ) > : public handler_type_base<_R>
	{
		typedef _P1 param1_type;
		typedef _P2 param2_type;
		typedef _P3 param3_type;

		virtual _R operator() ( _P1, _P2, _P3 ) = 0;
		virtual bool is_equal(handler_base*) = 0;
		virtual handler_base* clone() = 0;
	};

	// 4 param
	template <typename _R, typename _P1, typename _P2, typename _P3, typename _P4>
	struct handler_base<_R, TYPE_LIST4( _P1, _P2, _P3, _P4 ) > : public handler_type_base<_R>
	{
		typedef _P1 param1_type;
		typedef _P2 param2_type;
		typedef _P3 param3_type;
		typedef _P4 param4_type;

		virtual _R operator() ( _P1, _P2, _P3, _P4 ) = 0;
		virtual bool is_equal(handler_base*) = 0;
		virtual handler_base* clone() = 0;
	};

	// 5 param
	template <typename _R, typename _P1, typename _P2, typename _P3, typename _P4, typename _P5>
	struct handler_base<_R, TYPE_LIST5( _P1, _P2, _P3, _P4, _P5 ) > : public handler_type_base<_R>
	{
		typedef _P1 param1_type;
		typedef _P2 param2_type;
		typedef _P3 param3_type;
		typedef _P4 param4_type;
		typedef _P5 param5_type;

		virtual _R operator() ( _P1, _P2, _P3, _P4, _P5 ) = 0;
		virtual bool is_equal(handler_base*) = 0;
		virtual handler_base* clone() = 0;
	};

	// 6 param
	template <typename _R, typename _P1, typename _P2, typename _P3, typename _P4, typename _P5, typename _P6>
	struct handler_base<_R, TYPE_LIST6( _P1, _P2, _P3, _P4, _P5, _P6 ) > : public handler_type_base<_R>
	{
		typedef _P1 param1_type;
		typedef _P2 param2_type;
		typedef _P3 param3_type;
		typedef _P4 param4_type;
		typedef _P5 param5_type;
		typedef _P6 param6_type;

		virtual _R operator() ( _P1, _P2, _P3, _P4, _P5, _P6 ) = 0;
		virtual bool is_equal(handler_base*) = 0;
		virtual handler_base* clone() = 0;
	}; 



	template <typename _ParamList>
	class Event
	{
	public:
		Event(): _recursive(false), _calling(false), _enabled(true)
		{
		}

		typedef Functor<void, _ParamList> Handler;

		typedef handler_base<void, _ParamList> handler_type ;

		typedef typename handler_type::param1_type param1_type;
		typedef typename handler_type::param2_type param2_type;
		typedef typename handler_type::param3_type param3_type;
		typedef typename handler_type::param4_type param4_type;
		typedef typename handler_type::param5_type param5_type;
		typedef typename handler_type::param6_type param6_type;

		void SetEnabled(bool enabled)
		{
			_enabled = enabled;
		}
		void SetRecursive(bool recursive)
		{
			_recursive = recursive;
		}
		void Add(const Handler& eventHandler)
		{
			_eventHandlerList.push_back(eventHandler);
		}
		void Remove(const Handler& eventHandler)
		{
			_eventHandlerList.remove(eventHandler);
		}
		void Clear()
		{
			_eventHandlerList.clear();
		}
		bool Contains(const Handler& eventHandler)
		{
			EventHandlerList::iterator it;
			it = std::find(_eventHandlerList.begin(), _eventHandlerList.end(), eventHandler);
			return ( it != _eventHandlerList.end() );
		}
		size_t Count()
		{
			return _eventHandlerList.size();
		}

		void operator()()
		{
			if (!_enabled)
			{
				return;
			}
			if (_eventHandlerList.size() == 0)
			{
				return;
			}
			if ((!_recursive) && _calling)
			{
				return;
			}
			_calling = true;
			for (EventHandlerList::iterator it=_eventHandlerList.begin(); it!=_eventHandlerList.end(); ++it)
				(*it)();
			_calling = false;
		}
		void operator()(param1_type param1)
		{
			if (!_enabled)
			{
				return;
			}
			if (_eventHandlerList.size() == 0)
			{
				return;
			}
			if ((!_recursive) && _calling)
			{
				return;
			}
			_calling = true;
			for (EventHandlerList::iterator it=_eventHandlerList.begin(); it!=_eventHandlerList.end(); ++it)
				(*it)(param1);
			_calling = false;
		}
		void operator()(param1_type param1, param2_type param2)
		{
			if (!_enabled)
			{
				return;
			}
			if (_eventHandlerList.size() == 0)
			{
				return;
			}
			if ((!_recursive) && _calling)
			{
				return;
			}
			_calling = true;
			for (EventHandlerList::iterator it=_eventHandlerList.begin(); it!=_eventHandlerList.end(); ++it)
				(*it)(param1, param2);
			_calling = false;
		}
		void operator()(param1_type param1, param2_type param2, param3_type param3)
		{
			if (!_enabled)
			{
				return;
			}
			if (_eventHandlerList.size() == 0)
			{
				return;
			}
			if ((!_recursive) && _calling)
			{
				return;
			}
			_calling = true;
			for (EventHandlerList::iterator it=_eventHandlerList.begin(); it!=_eventHandlerList.end(); ++it)
				(*it)(param1, param2, param3);
			_calling = false;
		}
		void operator()(param1_type param1, param2_type param2, param3_type param3, param4_type param4)
		{
			if (!_enabled)
			{
				return;
			}
			if (_eventHandlerList.size() == 0)
			{
				return;
			}
			if ((!_recursive) && _calling)
			{
				return;
			}
			_calling = true;
			for (EventHandlerList::iterator it=_eventHandlerList.begin(); it!=_eventHandlerList.end(); ++it)
				(*it)(param1, param2, param3, param4);
			_calling = false;
		}
		void operator()(param1_type param1, param2_type param2, param3_type param3, param4_type param4, param5_type param5)
		{
			if (!_enabled)
			{
				return;
			}
			if (_eventHandlerList.size() == 0)
			{
				return;
			}
			if ((!_recursive) && _calling)
			{
				return;
			}
			_calling = true;
			for (EventHandlerList::iterator it=_eventHandlerList.begin(); it!=_eventHandlerList.end(); ++it)
				(*it)(param1, param2, param3, param4, param5);
			_calling = false;
		}
		void operator()(param1_type param1, param2_type param2, param3_type param3, param4_type param4, param5_type param5, param6_type param6)
		{
			if (!_enabled)
			{
				return;
			}
			if (_eventHandlerList.size() == 0)
			{
				return;
			}
			if ((!_recursive) && _calling)
			{
				return;
			}
			_calling = true;
			for (EventHandlerList::iterator it=_eventHandlerList.begin(); it!=_eventHandlerList.end(); ++it)
				(*it)(param1, param2, param3, param4, param5, param6);
			_calling = false;
		}

	private:
		typedef std::list< Handler > EventHandlerList;
		EventHandlerList _eventHandlerList;

		bool _recursive; // can recursively call, default is false;
		bool _calling;
		bool _enabled; // true:broadcast event; false:not droadcast event; default is true;
	};
};